#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>

#define MAXSIZE 1024

struct client
{
	unsigned short token;
	unsigned short port;
	unsigned int ip;
	time_t time;
	struct client *next;
};

int size = 0; //list

pthread_mutex_t mutex;

struct client head_m;
struct client *head = &head_m;

void Insert(struct sockaddr_in *cli, int token);

struct client *Search(int token);

void Delete(int token);

void *thread(void *vargp);

void parsemessage(char *buf, int fd, struct sockaddr_in *cli);

void Compare(void);

int main()
{
	pthread_t id;
	int ret;
	int fd = socket(PF_INET, SOCK_DGRAM, 0);
	if (fd == -1)
		perror("create failed!"), exit(-1);
	struct sockaddr_in ser_addr;
	struct sockaddr_in cli_addr;
	ser_addr.sin_family = PF_INET;
	ser_addr.sin_port = htons(12345);
	ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0)
	{
		perror("bind failed!1");
		exit(-1);
	}
	else
		printf("bind success!\n");

	int cli_len = sizeof(cli_addr);
	memset(&cli_addr, 0, cli_len);
	cli_addr.sin_family = PF_INET;
	char buf[MAXSIZE];
	memset(&cli_addr, 0, sizeof(cli_addr));

	// ret = pthread_create(&id, NULL, (void*)thread, NULL);
	// if(ret != 0)
	// {
	// 	printf("Create thread error!\r\n");
	// 	exit(1);
	// }
	while (1)
	{
		printf("wait client login......\n");
		memset(buf, 0, 1024);
		if ((recvfrom(fd, buf, MAXSIZE, 0, (struct sockaddr *)&cli_addr, (socklen_t *)&cli_len)) < 0)
		{
			perror("recv failed!1");
			break;
		}
		parsemessage(buf, fd, &cli_addr);
	}

	close(fd);
	return 0;
}

void parsemessage(char *buf, int fd, struct sockaddr_in *cli)
{
	unsigned short token;
	//memset(head, 0 , sizeof(head_m));
	memcpy(&token, buf, 2);
	token = ntohs(token);
	struct client *p;
	p = head;
	printf("\np->token : %x\n", p->token);
	if (p->token != 0)
	{
		struct sockaddr_in addr;
		addr.sin_family = PF_INET;
		addr.sin_port = htons(p->port);
		addr.sin_addr.s_addr = htonl(p->ip);
		memset(buf, 0, MAXSIZE);
		token = htons(token);
		memcpy(buf, &token, 2);
		memcpy(buf + 2, &addr.sin_port, 2);
		memcpy(buf + 4, &addr.sin_addr.s_addr, 4);
		memcpy(buf + 8, &(cli->sin_port), 2);
		memcpy(buf + 10, &(cli->sin_addr.s_addr), 4);
		printf("mubiao-> port:[%d], ip:[%s]\n", addr.sin_port, inet_ntoa(addr.sin_addr));
		printf("ziji---> port:[%d], ip:[%s]\n", cli->sin_port, inet_ntoa(cli->sin_addr));
		if (sendto(fd, buf, 14, 0, (struct sockaddr *)cli, sizeof(*cli)) < 0)
		{
			perror("send failed!1");
			exit(0);
		}
		memset(buf, 0, MAXSIZE);
		memcpy(buf, &token, 2);
		memcpy(buf + 2, &(cli->sin_port), 2);
		memcpy(buf + 4, &(cli->sin_addr.s_addr), 4);
		memcpy(buf + 8, &addr.sin_port, 2);
		memcpy(buf + 10, &addr.sin_addr.s_addr, 4);
		if (sendto(fd, buf, 14, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0)
		{
			perror("send failed!2");
			exit(0);
		}
		// pthread_mutex_lock(&mutex);
		// Delete(token);
		// pthread_mutex_unlock(&mutex);
		if (sendto(fd, "first\n", 14, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0)
		{
			perror("send failed!2");
			exit(0);
		}
		if (sendto(fd, "second\n", 14, 0, (struct sockaddr *)cli, sizeof(*cli)) < 0)
		{
			perror("send failed!1");
			exit(0);
		}
		memset(head, 0, sizeof(head_m));
		return;
	}
	if (p->token == 0)
	{
		head->port = ntohs(cli->sin_port);
		head->ip = ntohl(cli->sin_addr.s_addr);
		head->token = token;
		unsigned short token1;

		struct sockaddr_in addr;
		memset(buf, 0, MAXSIZE);
		token = htons(token);
		//memcpy(buf, &token1, 2);
		memcpy(buf + 2, &(cli->sin_port), 2);
		memcpy(buf + 4, &(cli->sin_addr.s_addr), 4);

		token1 = 0x0000;
		char buf1[30] = "server:[received!]\n";
		token1 = htons(token1);
		memcpy(buf, &token1, 2);
		memcpy(buf + 8, buf1, 30);
		printf("Sendto data [received!]\n");
		printf("ziji---> port:[%d], ip:[%s]\n", cli->sin_port, inet_ntoa(cli->sin_addr));
		if (sendto(fd, buf, 38, 0, (struct sockaddr *)cli, sizeof(*cli)) < 0)
		{
			perror("send failed!3");
			exit(1);
		}
	}
}

void Insert(struct sockaddr_in *cli, int token)
{
	struct client *p;
	time_t t = time(NULL);
	p = (struct client *)malloc(sizeof(struct client));
	p->port = ntohs(cli->sin_port);
	p->ip = ntohl(cli->sin_addr.s_addr);
	p->token = token;
	p->time = t;
	if (head == NULL)
	{
		p->next = NULL;
		head = p;
		p = NULL;
	}
	else
	{
		p->next = head;
		head = p;
		p = NULL;
	}
	size++;
}

struct client *Search(int token)
{
	struct client *p;
	p = head;
	while (p)
	{
		if (p->token == token)
		{
			return p;
		}
		p = p->next;
	}
	return p;
}

void Delete(int token)
{
	// struct client *p;
	// struct client *p1;
	// p = Search(token);
	int i;
	// p1 = head;
	// for(i = 1; i < size; i++)
	// {
	// 	if(p1->next == p)
	// 	{
	// 		p1->next = p->next;
	// 		free(p);
	// 		p = NULL;
	// 		p1 = NULL;
	// 		return;
	// 	}
	// 	p1 = p1->next;
	// }
	// free(p);
	// p = NULL;
	// p1 = NULL;
	// head = NULL;
	struct client *p1;
	for (i = 0; i < size; i++)
	{
		p1 = head;
		if (p1->next == NULL)
		{
			free(p1);
			return;
		}
		head = p1->next;
		free(p1);
	}
}